import os.path
import time
import math
import numpy as np
import geatpy as ea
import pandas as pd

from md import MyProblem, scatter_3d, result_format_output, calc_results, stand_score
from pqi import PQI


# class MyProblem(ea.Problem):  # 继承Problem父类
#     def __init__(self, qpi, RoadLength=51.544, budget=5000):
#         '''
#         RoadLength: float 维护路段总长度 (单位:KM)
#         budget: float 养护路段总预算 (单位: 万元)
#         '''
#         self.road_len = RoadLength
#         self.budget = budget
#         self.m = math.ceil(RoadLength)
#
#         self.pqi = qpi
#
#         # self.C = np.array([0, 18.7, 53, 82, 80, 168, 280, 520]).reshape(-1, 1)  # 养护措施j的单价
#         # self.E = np.array([0, 0.23, 0.8, 0.92, 1.44, 1.54, 1.60, 1.64]).reshape(-1, 1)  # 养护措施j的碳排放
#
#         # ###决策变量: 交通量(整数), 路面破损状况PDCI(实数), 车辙深度RD(整数), 国际平整度指数IRI(实数), 横向力系数SFC(整数), 维护路段idx
#         # 决策变量: 交通量(整数), 养护类别(整数)
#         name = 'MD'
#         T = 5
#         M = 3  # 初始化M（目标维数）
#         Dim = 1 + self.m  # 初始化Dim（决策变量维数x1,x2,x3）
#         maxormins = [-1, 1, 1]  # 初始化maxormins (目标最小最大化标记列表, 1: 最小化目标, -1: 最大化目标)
#         varTypes = [1] + [1] * self.m  # 初始化varTypes (决策变量类型, 0: 实数, 1: 整数)
#         lb = [0] + [0] * self.m  # + [0] * self.m  # 决策变量下界
#         ub = [3] + [7] * self.m  # + [self.m-1] * self.m  # 决策变量上界
#         lbin = [1] * Dim  # 决策变量下边界（0表示不包含该变量的下边界，1表示包含）
#         ubin = [1] * Dim  # 决策变量上边界（0表示不包含该变量的上边界，1表示包含）
#         # 调用父类构造方法完成实例化
#         ea.Problem.__init__(self,
#                             name,
#                             M,
#                             maxormins,
#                             Dim,
#                             varTypes,
#                             lb,
#                             ub,
#                             lbin,
#                             ubin)
#
#     # @ea.Problem.single
#     def evalVars(self, Vars):  # 目标函数
#         b = Vars[:, [0]]  # 交通量
#         js = Vars[:, 1:]  # 维护类别
#
#         f1 = self.pqi.F1(b, js)
#         f2 = self.pqi.F2(b, js)
#         f3 = self.pqi.F3(b, js)
#
#         f = np.hstack([f1, f2, f3])
#         # 约束条件
#         CV = np.hstack([
#             f2 - self.budget
#         ])
#         return f, CV


# maintainDept = p['maintainDept']
# roadNo = p['roadNo']
# roadLen = p['roadLen']
# duration = p['duration']
# budgetFee = p['budgetFee']
# trafficLevel = p['trafficLevel']

def result_format_output(ObjV, maintainDept, roadNo, startingStation, year, duration):
    # ObjV = result['ObjV']
    pqi = ObjV[:, [0]]
    cost = ObjV[:, [1]]
    carbon = ObjV[:, [2]]
    pqi_max = np.max(pqi)
    pqi_min = np.min(pqi)
    cost_max = np.max(cost)
    cost_min = np.min(cost)
    carbon_max = np.max(carbon)
    carbon_min = np.min(carbon)
    print('PQI max: {}, min: {}'.format(pqi_max, pqi_min))
    print('const max: {}, min: {}'.format(cost_max, cost_min))
    print('carbon max: {}, min: {}'.format(carbon_max, carbon_min))
    pqi_score = stand_score(pqi, pqi_max, pqi_min)
    cost_score = stand_score(cost, cost_max, cost_min)
    carbon_score = stand_score(carbon, carbon_max, carbon_min)
    scores = 0.4 * pqi_score + 0.4 * cost_score + 0.2 * carbon_score
    print(scores)
    print(type(scores))

    # df = pd.DataFrame(columns=['养护费用', '标准化分值', '碳排放量', '标准化分值', '路面质量指数', '标准化分值', '总分'])
    data = np.hstack((cost, cost_score, carbon, carbon_score, pqi, pqi_score, scores))
    df = pd.DataFrame(data, columns=['养护费用', '标准化分值', '碳排放量', '标准化分值', '路面质量指数', '标准化分值',
                                     '总分'])
    print(df)
    filename = 'outputs/{}_{}_{}({}-{}).csv'.format(maintainDept, roadNo, startingStation, year, year + duration)
    df.to_csv(filename)
    print('Max score index: {}'.format(np.argmax(scores)))
    return filename


def calc_result_optimal(ObjV):
    # ObjV = result['ObjV']
    pqi = ObjV[:, [0]]
    cost = ObjV[:, [1]]
    carbon = ObjV[:, [2]]
    pqi_max = np.max(pqi)
    pqi_min = np.min(pqi)
    cost_max = np.max(cost)
    cost_min = np.min(cost)
    carbon_max = np.max(carbon)
    carbon_min = np.min(carbon)
    # print('PQI max: {}, min: {}'.format(pqi_max, pqi_min))
    # print('const max: {}, min: {}'.format(cost_max, cost_min))
    # print('carbon max: {}, min: {}'.format(carbon_max, carbon_min))
    pqi_score = stand_score(pqi, pqi_max, pqi_min)
    cost_score = stand_score(cost, cost_max, cost_min)
    carbon_score = stand_score(carbon, carbon_max, carbon_min)
    scores = 0.4 * pqi_score + 0.4 * cost_score + 0.2 * carbon_score
    # print(scores)
    # print(type(scores))

    # # df = pd.DataFrame(columns=['养护费用', '标准化分值', '碳排放量', '标准化分值', '路面质量指数', '标准化分值', '总分'])
    # data = np.hstack((cost, cost_score, carbon, carbon_score, pqi, pqi_score, scores))
    # df = pd.DataFrame(data, columns=['养护费用', '标准化分值', '碳排放量', '标准化分值', '路面质量指数', '标准化分值',
    #                                  '总分'])
    # print(df)
    # df.to_csv('outputs/养护方案1.csv')
    # print('Max score index: {}'.format(np.argmax(scores)))
    return np.argmax(scores)


def web_query_maintance(maintainDept, roadNo, startingStation, RoadLen, duration, budgetFee, trafficLevel, lineTotal):
    localtime = time.localtime(time.time())
    year = localtime[0]
    # PQI __init__(self, L=52, T=5, B=0, N=1):
    pqi = PQI(L=math.ceil(RoadLen), T=duration, B=1, N=lineTotal)

    # 实例化问题对象
    problem = MyProblem(pqi, RoadLen, budgetFee)

    # 构造算法
    algorithm = ea.moea_NSGA2_templet(
        problem,
        ea.Population(Encoding='RI', NIND=100),
        MAXGEN=300,  # 最大进化代数
        logTras=1  # 表示每隔多少代记录一次日志, 0表示不记录
    )
    # algorithm.mutOper.Pm = 0.6  # 修改变异算子的变异概率
    # algorithm.recOper.XOVR = 0.8  # 修改交叉算子的交叉概率

    # 求解
    res = ea.optimize(algorithm,
                      verbose=True,
                      drawing=1,
                      outputMsg=True,
                      drawLog=True,
                      saveFlag=True,
                      dirName='result')
    print('result: {}'.format(res))
    if res['success']:
        ObjV = res['ObjV']
        max_idx = calc_result_optimal(ObjV)
        Vars = res['Vars']
        # calc_result(self, j, maintainDept, roadNo, startingStation, year, duration)
        csvfile = pqi.calc_result(Vars[max_idx], maintainDept, roadNo, startingStation, year, duration)
        if os.path.exists(csvfile):
            return csvfile

        # csvfile = result_format_output(ObjV, maintainDept, roadNo, startingStation, year, duration)
        # if os.path.exists(csvfile):
        #     return csvfile
